// FPGA projects, Verilog projects, VHDL projects
// Verilog code for TIC TAC TOE GAME 
// Top level module  
module tic_tac_toe_game(
     input clock, // clock of the game 
     input reset, // reset button to reset the game 
     input play, // play button to enable player to play 
     input pc, // pc button to enable computer to play 
     input [3:0] computer_position,player_position, 
     // positions to play 
     output wire [1:0] pos1,pos2,pos3,
     pos4,pos5,pos6,pos7,pos8,pos9,
     // LED display for positions 
     // 01: Player 
     // 10: Computer 
     output wire[1:0]who 
     // who the winner is 
     );
 wire [15:0] PC_en;// Computer enable signals 
 wire [15:0] PL_en; // Player enable signals 
 wire illegal_move; // disable writing when an illegal move is detected 
 //wire [1:0] pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9;// positions stored
 wire win; // win signal 
 wire computer_play; // computer enabling signal 
 wire player_play; // player enabling signal 
 wire no_space; // no space signal 
 // position registers    
  position_registers position_reg_unit(
      clock, // clock of the game 
      reset, // reset the game 
      illegal_move, // disable writing when an illegal move is detected 
      PC_en[8:0], // Computer enable signals 
      PL_en[8:0], // Player enable signals 
      pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9// positions stored
      );
 // winner detector 
 winner_detector win_detect_unit(pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9,win,who);
 // position decoder for computer 
 position_decoder pd1(computer_position,computer_play,PC_en);
 // position decoder for player  
 position_decoder pd2(player_position,player_play,PL_en); 
 // illegal move detector
  illegal_move_detector imd_unit(
   pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9, 
   PC_en[8:0], PL_en[8:0], 
   illegal_move
   );
 // no space detector 
 nospace_detector nsd_unit(
   pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9, 
   no_space
    ); 
 fsm_controller tic_tac_toe_controller(
     clock,// clock of the circuit 
     reset,// reset 
     play, // player plays 
     pc,// computer plays 
     illegal_move,// illegal move detected 
     no_space, // no_space detected 
     win, // winner detected 
     computer_play, // enable computer to play 
     player_play // enable player to play 
     );    
endmodule 
// Position registers 
// fpga4student.com: FPGA projects, Verilog projects, VHDL projects
// to store player or computer positions 
// when enabling by the FSM controller 
module position_registers(
      input clock, // clock of the game 
      input reset, // reset the game 
      input illegal_move, // disable writing when an illegal move is detected 
      input [8:0] PC_en, // Computer enable signals 
      input [8:0] PL_en, // Player enable signals 
      output reg[1:0] pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9// positions stored
      );
 // Position 1 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos1 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos1 <= pos1;// keep previous position
   else if(PC_en[0]==1'b1)
    pos1 <= 2'b10; // store computer data 
   else if (PL_en[0]==1'b1)
    pos1 <= 2'b01;// store player data 
   else 
    pos1 <= pos1;// keep previous position
  end 
 end 
 // Position 2 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos2 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos2 <= pos2;// keep previous position
   else if(PC_en[1]==1'b1)
    pos2 <= 2'b10; // store computer data 
   else if (PL_en[1]==1'b1)
    pos2 <= 2'b01;// store player data 
   else 
    pos2 <= pos2;// keep previous position
  end 
 end 
// Position 3 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos3 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos3 <= pos3;// keep previous position
   else if(PC_en[2]==1'b1)
    pos3 <= 2'b10; // store computer data 
   else if (PL_en[2]==1'b1)
    pos3 <= 2'b01;// store player data 
   else 
    pos3 <= pos3;// keep previous position
  end 
 end  
 // Position 4 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos4 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos4 <= pos4;// keep previous position
   else if(PC_en[3]==1'b1)
    pos4 <= 2'b10; // store computer data 
   else if (PL_en[3]==1'b1)
    pos4 <= 2'b01;// store player data 
   else 
    pos4 <= pos4;// keep previous position
  end 
 end 
 // Position 5 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos5 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos5 <= pos5;// keep previous position
   else if(PC_en[4]==1'b1)
    pos5 <= 2'b10; // store computer data 
   else if (PL_en[4]==1'b1)
    pos5 <= 2'b01;// store player data 
   else 
    pos5 <= pos5;// keep previous position
  end 
 end 
 // Position 6 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos6 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos6 <= pos6;// keep previous position
   else if(PC_en[5]==1'b1)
    pos6 <= 2'b10; // store computer data 
   else if (PL_en[5]==1'b1)
    pos6 <= 2'b01;// store player data 
   else 
    pos6 <= pos6;// keep previous position
  end 
 end 
 // Position 7 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos7 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos7 <= pos7;// keep previous position
   else if(PC_en[6]==1'b1)
    pos7 <= 2'b10; // store computer data 
   else if (PL_en[6]==1'b1)
    pos7 <= 2'b01;// store player data 
   else 
    pos7 <= pos7;// keep previous position
  end 
 end 
 // Position 8 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos8 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos8 <= pos8;// keep previous position
   else if(PC_en[7]==1'b1)
    pos8 <= 2'b10; // store computer data 
   else if (PL_en[7]==1'b1)
    pos8 <= 2'b01;// store player data 
   else 
    pos8 <= pos8;// keep previous position
  end 
 end 
 // Position 9 
 always @(posedge clock or posedge reset)
 begin
  if(reset) 
   pos9 <= 2'b00;
  else begin
   if(illegal_move==1'b1)
    pos9 <= pos9;// keep previous position
   else if(PC_en[8]==1'b1)
    pos9 <= 2'b10; // store computer data 
   else if (PL_en[8]==1'b1)
    pos9 <= 2'b01;// store player data 
   else 
    pos9 <= pos9;// keep previous position
  end 
 end  
endmodule